package com.business_clean.ui.activity.address;

import static me.hgj.mvvmhelper.ext.CommExtKt.isLocationOpen;

import androidx.annotation.NonNull;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.LinearLayoutManager;

import android.content.Context;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.ImageView;
import android.widget.ZoomControls;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.Poi;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.poi.OnGetPoiSearchResultListener;
import com.baidu.mapapi.search.poi.PoiDetailResult;
import com.baidu.mapapi.search.poi.PoiDetailSearchOption;
import com.baidu.mapapi.search.poi.PoiDetailSearchResult;
import com.baidu.mapapi.search.poi.PoiIndoorResult;
import com.baidu.mapapi.search.poi.PoiNearbySearchOption;
import com.baidu.mapapi.search.poi.PoiResult;
import com.baidu.mapapi.search.poi.PoiSearch;
import com.blankj.utilcode.util.KeyboardUtils;
import com.business_clean.app.App;
import com.business_clean.app.base.BaseActivity;
import com.business_clean.app.config.Constant;
import com.business_clean.app.service.LocService;
import com.business_clean.app.uitl.ToastUtil;
import com.business_clean.data.mode.address.CustomPoiEntity;
import com.business_clean.databinding.ActivityAddAddressBinding;
import com.business_clean.ui.adapter.AddressChooseAdapter;
import com.business_clean.viewmodel.request.AddressViewModel;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.listener.OnItemClickListener;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import me.hgj.mvvmhelper.ext.LogExtKt;

public class AddAddressActivity extends BaseActivity<AddressViewModel, ActivityAddAddressBinding> {

    private BaiduMap mBaiduMap;
    private LocService locService;

    private AddressChooseAdapter mAdapter;
    private PoiSearch mPoiSearch;

    private BDLocation bdLocation;//获取百度地图的定位信息

    private boolean isFirst = true;


    // 创建GeoCoder实例
    private GeoCoder geoCoder = GeoCoder.newInstance();

    @Override
    public void initView(@Nullable Bundle savedInstanceState) {
        mBaiduMap = mDatabind.map.getMap();
        mAdapter = new AddressChooseAdapter();
        mDatabind.recycler.setAdapter(mAdapter);
        mDatabind.recycler.setLayoutManager(new LinearLayoutManager(this));
        initMapConfig();
        initLocation();
        if (!isLocationOpen(this)) {
            ToastUtil.show("无法获取定位，请开启手机的定位服务。");
        }
    }



    private void initMapConfig() {
        //隐藏logo
        View child = mDatabind.map.getChildAt(1);
        if (child != null && (child instanceof ImageView || child instanceof ZoomControls)) {
            child.setVisibility(View.INVISIBLE);
        }
        // 不显示地图上比例尺
        mDatabind.map.showScaleControl(false);
        mDatabind.map.showZoomControls(false);
    }

    private void initLocation() {
        XXPermissions.with(this)
                .permission(Permission.ACCESS_FINE_LOCATION, Permission.ACCESS_COARSE_LOCATION)
                .request(new OnPermissionCallback() {
                    @Override
                    public void onGranted(@NonNull @NotNull List<String> permissions, boolean allGranted) {
                        if (allGranted) {
                            startLocation();
                        }
                    }
                });
    }

    //初始化
    private void startLocation() {
        locService = new LocService(this);
        locService.registerListener(mListener);
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        // 开启定位图层
        mBaiduMap.setMyLocationEnabled(true);
        mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(17.0f));
        locService.setLocationOption(locService.getDefaultLocationClientOption());
        locService.start();
        //poi 搜索
        mPoiSearch = PoiSearch.newInstance();
        mPoiSearch.setOnGetPoiSearchResultListener(listener);
    }

    //定位到当前位置
    private void currentLocation(double latitude, double longitude) {
        MyLocationData locData = new MyLocationData.Builder()
//                .accuracy(location.getRadius())
                .latitude(latitude)
                .longitude(longitude)
                .build();
        mBaiduMap.setMyLocationData(locData);


        MyLocationConfiguration config = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL, true, null);
        mBaiduMap.setMyLocationConfiguration(config);

        LatLng currentLatLng = new LatLng(latitude, longitude);
        MapStatus.Builder builder = new MapStatus.Builder();
        builder.target(currentLatLng).zoom(17.0f);
        mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
    }

    private void setPoiList(List<Poi> poiList) {
        if (bdLocation == null) {
            return;
        }
        List<CustomPoiEntity> pois = new ArrayList<>();
        for (int i = 0; i < poiList.size(); i++) {
//                LogExtKt.logE("1 -> " + poiResult.getAllPoi().get(i).getDirection() + " 2->" + poiResult.getAllPoi().get(i).getAddress()
//                        + " 3->" + poiResult.getAllPoi().get(i).getArea() + " 4->" + poiResult.getAllPoi().get(i).getDetail(), LogExtKt.TAG);
            pois.add(new CustomPoiEntity(
                    poiList.get(i).getRank(),
                    poiList.get(i).getId(),
                    poiList.get(i).getName(),
                    poiList.get(i).getAddr(),
                    poiList.get(i).getAddr(),
                    bdLocation.getLatitude(),
                    bdLocation.getLongitude()));
        }
        mAdapter.setList(pois);
    }

    @Override
    public void onBindViewClick() {
        mDatabind.ivNowLocation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                currentLocation(bdLocation.getLatitude(), bdLocation.getLongitude());
            }
        });
    }

    @Override
    public void onRequestSuccess() {
        mViewModel.getSaveAddress().observe(this, new Observer<Object>() {
            @Override
            public void onChanged(Object o) {
                App.appViewModelInstance.getRefreshAddressManagerList().setValue(true);
                finish();
            }
        });
    }

    @Override
    public void initObserver() {
        mAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(@NonNull @NotNull BaseQuickAdapter<?, ?> adapter, @NonNull @NotNull View view, int position) {
                HashMap<String, String> hashMap = new HashMap<>();
                hashMap.put("project_uuid", "" + App.appViewModelInstance.getUserInfo().getValue().getProject().getUuid());
                hashMap.put("address", "" + mAdapter.getData().get(position).getName());
                hashMap.put("address_desc", "" + mAdapter.getData().get(position).getAddr());
                hashMap.put("lnt", "" + mAdapter.getData().get(position).getLnt());
                hashMap.put("lat", "" + mAdapter.getData().get(position).getLat());
                mViewModel.requestSaveAddress(hashMap);
            }
        });


        mDatabind.etSearchAddress.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                if (!TextUtils.isEmpty(s.toString())) {
                    LogExtKt.logE("来查询了：", "");
                    if (bdLocation != null) {
                        searchInputPoiList(new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude()), s.toString());
                    } else {
                        locService.start();//就去获取定位
                    }
                } else {
                    if (bdLocation != null) {
                        searchInputPoiList(new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude()), "");
                    }
                }
            }
        });

        mDatabind.flSearch.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switchSearchStatus(true);
            }
        });

        //取消搜索
        mDatabind.tvSearchCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                switchSearchStatus(false);
                mDatabind.etSearchAddress.setText("");
                getCurrentLocation();
            }
        });


        //增加Marker拖拽定位
        mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus) {
            }

            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus, int i) {
            }

            @Override
            public void onMapStatusChange(MapStatus mapStatus) {
            }

            @Override
            public void onMapStatusChangeFinish(MapStatus mapStatus) {
                logMsg("onMapStatusChangeFinish - " + mapStatus.target);
                if (!isFirst) {
                    //在这里根据拿到的定位信息，重新去获取Poi
                    ReverseGeoCodeOption option = new ReverseGeoCodeOption();
                    option.location(mapStatus.target); // 设置经纬度
                    // 发起逆地理编码查询
                    geoCoder.reverseGeoCode(option);
                }
            }
        });

        geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
            @Override
            public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
                logMsg("onGetGeoCodeResult");
            }

            @Override
            public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
                logMsg("onGetReverseGeoCodeResult");
                if (reverseGeoCodeResult == null || reverseGeoCodeResult.error != SearchResult.ERRORNO.NO_ERROR) {
                    // 处理错误情况
                    return;
                }
                if (!isFirst) {
                    if (reverseGeoCodeResult.getPoiList() != null) {
                        logMsg("onGetReverseGeoCodeResult" + reverseGeoCodeResult.getPoiList().size());
                        mAdapter.setList(getPoiList(reverseGeoCodeResult.getPoiList()));
                    } else {
                        logMsg("onGetReverseGeoCodeResult listsize = 0 ");
                    }
                }
            }
        });

        //地图加载完成事件响应
        mBaiduMap.setOnMapLoadedCallback(new BaiduMap.OnMapLoadedCallback() {
            @Override
            public void onMapLoaded() {
                //地图的有些操作需要再加载完成之后进行
            }
        });

    }

    private void switchSearchStatus(boolean show) {
        mDatabind.llSearchEt.setVisibility(show ? View.VISIBLE : View.GONE);
        mDatabind.tvSearchTitle.setVisibility(show ? View.GONE : View.VISIBLE);
        if (show) {
            KeyboardUtils.showSoftInput(mDatabind.etSearchAddress);
        } else {
            KeyboardUtils.hideSoftInput(mDatabind.etSearchAddress);
        }
    }

    /**
     * 获取当前的定位信息
     */
    private void getCurrentLocation() {
        if (bdLocation != null && bdLocation.getPoiList() != null) {
            setPoiList(bdLocation.getPoiList());
        }
    }

    /**
     * 根据输入的内容去查询Poi列表
     *
     * @param poiAddress
     */
    private void searchInputPoiList(LatLng latLng, String poiAddress) {
        LogExtKt.logE("来查询了：" + poiAddress, "");
        PoiNearbySearchOption params = new PoiNearbySearchOption();
        params.location(latLng)//筛选当前位置内的 内容
                .radius(300)//筛选300米内的内容
                .keyword(poiAddress)//支持多个关键字并集检索，不同关键字间以$符号分隔，最多支持10个关键字检索。如:”银行$酒店”
                .scope(2)//值为2，返回POI详细信息
                .pageCapacity(10);
        mPoiSearch.searchNearby(params);
    }


    @Override
    protected void onResume() {
        super.onResume();
        mDatabind.map.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mDatabind.map.onPause();
    }

    @Override
    protected void onStop() {
        locService.unregisterListener(mListener); //注销掉监听
        locService.stop();
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        mDatabind.map.onDestroy();
        if (mBaiduMap != null) {
            mBaiduMap.clear();
            mBaiduMap = null;
        }
        if (null != locService) {
            locService.unregisterListener(mListener); //注销掉监听
            locService.disableAssistantLocation();
            locService.stop();
        }
        mPoiSearch.destroy();
        super.onDestroy();
    }


    private BDAbstractLocationListener mListener = new BDAbstractLocationListener() {

        /**
         * 定位请求回调函数
         * @param location 定位结果
         */
        @Override
        public void onReceiveLocation(BDLocation location) {
            logMsg("location" + location.getTime());
            bdLocation = location;
            // TODO Auto-generated method stub
            if (null != location && location.getLocType() != BDLocation.TypeServerError) {
                currentLocation(location.getLatitude(), location.getLongitude());
                if (location.getPoiList() != null) {
                    logMsg("location-> " + location.getPoiList().size());
                }
//                setPoiList(location.getPoiList());
                isFirst = false;
            }
        }

        @Override
        public void onConnectHotSpotMessage(String s, int i) {
            super.onConnectHotSpotMessage(s, i);
        }

        /**
         * 回调定位诊断信息，开发者可以根据相关信息解决定位遇到的一些问题
         * @param locType 当前定位类型
         * @param diagnosticType 诊断类型（1~9）
         * @param diagnosticMessage 具体的诊断信息释义
         */
        @Override
        public void onLocDiagnosticMessage(int locType, int diagnosticType, String diagnosticMessage) {
            super.onLocDiagnosticMessage(locType, diagnosticType, diagnosticMessage);
            String tips = "";
            if (locType == BDLocation.TypeNetWorkLocation) {
                if (diagnosticType == 1) {
                    tips = ("网络定位成功，没有开启GPS，建议打开GPS会更好");
                } else if (diagnosticType == 2) {
                    tips = ("网络定位成功，没有开启Wi-Fi，建议打开Wi-Fi会更好");
                }
            } else if (locType == BDLocation.TypeOffLineLocationFail) {
                if (diagnosticType == 3) {
                    tips = ("定位失败，请您检查您的网络状态");
                }
            } else if (locType == BDLocation.TypeCriteriaException) {
                if (diagnosticType == 4) {
                    tips = ("定位失败，无法获取任何有效定位依据");
                } else if (diagnosticType == 5) {
                    tips = ("定位失败，无法获取有效定位依据，请检查运营商网络或者Wi-Fi网络是否正常开启，尝试重新请求定位");
                } else if (diagnosticType == 6) {
                    tips = ("定位失败，无法获取有效定位依据，请尝试插入一张sim卡或打开Wi-Fi重试");
                } else if (diagnosticType == 7) {
                    tips = ("定位失败，飞行模式下无法获取有效定位依据，请关闭飞行模式重试");
                } else if (diagnosticType == 9) {
                    tips = ("定位失败，无法获取任何有效定位依据");
                }
            } else if (locType == BDLocation.TypeServerError) {
                if (diagnosticType == 8) {
                    tips = ("定位失败，请确认您定位的开关打开状态，是否赋予APP定位权限");
                }
            }
            ToastUtil.show(tips);
        }
    };


    private OnGetPoiSearchResultListener listener = new OnGetPoiSearchResultListener() {
        @Override
        public void onGetPoiResult(PoiResult poiResult) {
            logMsg("onGetPoiResult = " + poiResult.error);
            if (poiResult.error != SearchResult.ERRORNO.NO_ERROR) {//没错误
                if (poiResult.error == SearchResult.ERRORNO.PERMISSION_UNFINISHED) {
                    ToastUtil.show("鉴权未成功，请退出app清除后台应用再重启哦");
                }
                return;
            }
            if (mAdapter != null) {
                mAdapter.setList(getPoiList(poiResult.getAllPoi()));
            }
        }

        @Override
        public void onGetPoiDetailResult(PoiDetailSearchResult poiDetailSearchResult) {
            logMsg("onGetPoiDetailResult");
        }

        @Override
        public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
            logMsg("onGetPoiIndoorResult");
        }

        //废弃
        @Override
        public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {

        }
    };


    private List<CustomPoiEntity> getPoiList(List<PoiInfo> poiResults) {
        List<CustomPoiEntity> pois = new ArrayList<>();
        for (int i = 0; i < poiResults.size(); i++) {
            logMsg("1 -> " + poiResults.get(i).getDirection() + " 2->" + poiResults.get(i).getAddress()
                    + " 3->" + poiResults.get(i).getArea() + " 4->" + poiResults.get(i).getDetail()
                    + " 6 -> " + poiResults.get(i).getLocation().latitude
                    + " 7 -> " + poiResults.get(i).getLocation().longitude
                    + "8->" + poiResults.get(i).getName());
            pois.add(new CustomPoiEntity(
                    poiResults.get(i).getDistance(),
                    poiResults.get(i).getUid(),
                    poiResults.get(i).getName(),
                    poiResults.get(i).getArea(),
                    poiResults.get(i).getAddress(),
                    poiResults.get(i).getLocation().latitude,
                    poiResults.get(i).getLocation().longitude));
        }
        return pois;
    }

    public void logMsg(final String str) {
        LogExtKt.logE(str, "AddressActivity");
    }
}